package peer.gui;

import java.awt.Container;
import java.net.InetAddress;

import javax.swing.JFrame;
import javax.swing.JTabbedPane;

import peer.SharingManager.FileReference;


/**The graphic user interface for the client. When instantiated, it creates and displays itself. Other parts of the
 * client call methods in this to change the data that is being displayed. It also reacts to user input.
 * @author David Johnstone
 *
 */
public class PeerGUI extends JFrame
{
	private static PeerGUI Singleton;
	NetworkPanel networkPanel;
	LibraryPanel libraryPanel;
	SearchPanel searchPanel;
	DownloadPanel downloadPanel;
	LogPanel logPanel;
	
	private PeerGUI()
	{
		super("NFP Peer");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(600, 450);
		Container pane = getContentPane();
		
		JTabbedPane tabbedPane = new JTabbedPane();
		networkPanel = new NetworkPanel();
		libraryPanel = new LibraryPanel();
		searchPanel = new SearchPanel(this);
		downloadPanel = new DownloadPanel();
		logPanel = new LogPanel();
		
		tabbedPane.addTab("Network", networkPanel);
		tabbedPane.add("Library", libraryPanel);
		tabbedPane.addTab("Search", searchPanel);
		tabbedPane.addTab("Download", downloadPanel);
		tabbedPane.addTab("Log", logPanel);
		
		pane.add(tabbedPane);
		
		setVisible(true);
	}
	
	
	public static PeerGUI instance()
	{
		if(Singleton == null)
			Singleton = new PeerGUI();
		
		return Singleton;
		
	}
	
	//method to change the connection status
	
	
	/**Call when the nw_connect_accept message is received or the nw_connect message we sent has timed out
	 * @param connected true if nw_connect_accept was received, false if our message timed out
	 */
	public void connectionAccepted(boolean connected)
	{
		networkPanel.connectionAccepted(connected);
	}
	
	/**Call when a nw_newpeers_accept message is received or our nw_newpeers message has timed out
	 * @param addresses the value of the peer_list header in nw_newpeers_accept, or null if not received
	 */
	public void addNewPeers(String addresses)
	{
		networkPanel.addNewPeers(addresses);
	}
	
	
	/**Removes an address from the list of connections to the overlay network.
	 * Call this when a peer doesn't respond to pings.
	 * @param address address to remove
	 * @return true if the address was able to be removed (false if address not found)
	 */
	public boolean removeNetworkConnection(InetAddress address)
	{
		return true;//TODO: fix implementation of removeConnection
		//return networkPanel.removeConnection(address.getHostAddress());
	}
	
	

	public void addFileToLibrary(FileReference fr)
	{
		try
		{
		libraryPanel.addFile(fr);
		}
		catch (Exception e)
		{
			
		}
	}
	
	//methods for searching
	
	
	/**Adds a search result to the appropriate table. If the file has already been added, it will increment the list of peers.
	 * @param query the query for which the file matched
	 * @param filename the name of the file
	 * @param size size of the file in bytes
	 * @param hashcode hash code as a hex string
	 */
	public void addSearchResult(String query, String filename, long size, String hashcode)
	{
		searchPanel.addSearchResult(query, filename, size, hashcode);
	}
	
	//methods for download
	
	/**Set up the gui to download a file. This method is called when the download file button is clicked, so there is no reason
	 * to call it when building upon this gui.
	 * @param name file name
	 * @param peers number of peers
	 * @param size file size in bytes
	 * @param hashcode hash code in hex string
	 */
	public void setDownloadFile(String name, int peers, long size, String hashcode)
	{
		downloadPanel.setDownloadFile(name, peers, size, hashcode);
	}
	
	/**Add a peer to the list of peers which have the file being downloaded.
	 * Call this when we know of a new peer which has or wants the file.
	 * @param address IP Address as string
	 * @param percentCompleted percentage of the file they have
	 */
	public void addPeer(String address, int port, double percentCompleted)
	{
		downloadPanel.addPeer(address, port, percentCompleted);
	}
	
	/**Update the file completion status of a peer who is downloading the file we are.
	 * Call this when we receive a status update from a peer.
	 * @param address IP address
	 * @param percentCompleted the new completion amount
	 */
	public void updatePeerFileCompletion(String address, int port, double percentCompleted)
	{
		downloadPanel.updatePeerFileCompletion(address, port, percentCompleted);
	}
	
	/**Tells the gui which block we are getting from another peer.
	 * Call this when we request a block from a peer.
	 * @param address IP address of peer
	 * @param block number of block we are getting
	 */
	public void updatePeerGettingBlock(String address, int port, int block)
	{
		downloadPanel.updatePeerGettingBlock(address, port, block);
	}
	
	/**Removes a peer from the list of peers that are downloading the same file we are
	 * Call this when a peer doesn't respond.
	 * @param address IP address of peer
	 * @return true if they were removed (false if the address doesn't exist in the list)
	 */
	public boolean removePeer(String address)
	{
		return downloadPanel.removePeer(address);
	}
	
	/**Increment the blocks completed count for a chunk. Call this when a block has been download.
	 * @param chunk
	 */
	public void completedBlock(int block)
	{
		downloadPanel.completedBlock(block);
	}
	
	
	//method for log
	public void writeLog(String string)
	{
		logPanel.writeLog(string);
	}
	
	
	////////REMOVED METHODS 
	/**Changes the status message for the connection between this client and the server.
	 * @param status not connected, connecting, connected
	 *//*
	public void setConnectionStatus(String status)
	{
		networkPanel.setConnectionStatus(status);
	}
	
	//methods for adding and removing connections to the overlay network
	
	*//**Adds a connection to the list of connections to the overlay network.
	 * @param address IP address to add
	 *//*
	public void addNetworkConnection(String address, int port)
	{
		networkPanel.addConnection(address, port);
	}
	
	*//**Adds a connection to the list of connections to the overlay network.
	 * @param address to add
	 *//*
	public void addNetworkConnection(InetAddress address, int port)
	{
		networkPanel.addConnection(address.getHostAddress(), port);
	}
	
	*//**Removes an address from the list of connections to the overlay network.
	 * Call this when a peer doesn't respond to pings.
	 * @param address IP address to remove
	 * @return true if the address was able to be removed (false if address not found)
	 *//*
	public boolean removeNetworkConnection(String address, int port)
	{
		return networkPanel.removeConnection(address, port);
	}
	
	*//**Removes an address from the list of connections to the overlay network.
	 * Call this when a peer doesn't respond to pings.
	 * @param address address to remove
	 * @return true if the address was able to be removed (false if address not found)
	 *//*
	public boolean removeNetworkConnection(InetAddress address, int port)
	{
		return networkPanel.removeConnection(address.getHostAddress(), port);
	}
	
	
	
	*/
	
	public void setConnectionStatus(String status)
	{
		networkPanel.setConnectionStatus(status);
	}
}
